package com.blog.utils;

import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * @author: chengqiang
 * @date: 2018/12/6 13:20
 * 提供原生sql执行
 */
@Service
public class BaseService<T, Dao extends BaseDao<T, Long>> {

    public Class<Dao> getDaoClass() {
        return (Class<Dao>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
    }

    @PersistenceContext
    private EntityManager entityManager;
    /**
     * 注入泛型中的Dao
     */
    protected Dao dao;
    public Dao getDao() {
        return dao;
    }
    public void setDao(Dao dao) {
        this.dao = SpringUtil.getBean(getDaoClass());
    }

    public List<Map<String, Object>> nativeQueryForListMap(String sql) {
        List<Map<String, Object>> list = nativeQueryForListMap(sql, new ArrayList<>());
        return list;
    }

    public List<Map<String, Object>> nativeQueryForListMap(String sql, List<Object> params) {
        sql = sql.toLowerCase();
        Query query = entityManager.createNativeQuery(sql);
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        for (int i = 0; i < params.size(); i++) {
            query.setParameter(i + 1, params.get(i));
        }
        return query.getResultList();
    }

    public List<Map<String, Object>> nativeQueryForListMap(String sql, Object... params) {
        List<Object> paramList = Arrays.asList(params);
        return nativeQueryForListMap(sql, paramList);
    }

    @Transactional(rollbackFor = Exception.class)
    public int executeNativeUpdate(String sql, Object... params) {
        List<Object> paramList = Arrays.asList(params);
        return executeNativeUpdate(sql, paramList);
    }

    @Transactional(rollbackFor = Exception.class)
    public int executeNativeUpdate(String sql, List<Object> params) {
        sql = sql.toLowerCase();
        if (sql.indexOf("where") == -1) {
            throw new RuntimeException("无法执行不含where条件的sql更新语句");
        }
        Query query = entityManager.createNativeQuery(sql);
        for (int i = 0; i < params.size(); i++) {
            query.setParameter(i + 1, params.get(i));
        }
        return query.executeUpdate();
    }

}
